/*
 * This file is part of the Boring Engine.
 *
 * Copyright (c) 2011 by pf5234 <pf5234@users.sourceforge.net>.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package com.googlecode.boringengine;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Calendar;
import java.util.TimeZone;

public class Log {

    private static PrintStream error = System.err;
    private static PrintStream logfi;
    private static boolean logLoaded = false;

    private static void write(String type, String format, Object... args) {
        if (!logLoaded)
            loadlogfile();
        String str = String.format(format, args);
        String log = String.format("%s [%s]: %s: %s", getTime(), type, getPrevClass(), str);
        if (error != null)
            error.println(log);
        if (logfi != null)
            logfi.println(log);
    }

    public static void warn(String warn, Object... args) {
        write("Warning", warn, args);
    }

    public static void warnException(Exception e, String warn, Object... args) {
        String format = warn + "\n" + Util.stringifyException(e);
        write("Warning", format, args);
    }

    public static void error(String err, Object... args) {
        write("Error", err, args);
    }

    public static void errorException(Exception e, String err, Object... args) {
        String format = err + "\n" + Util.stringifyException(e);
        write("Error", format, args);
    }

    public static void fatal(String err, Object... args) {
        write("Fatal Error", err, args);
        doFatalCleanup();
    }
    
    public static void fatalException(Exception e, String err, Object... args) {
        String format = err + "\n" + Util.stringifyException(e);
        write("Fatal Error", format, args);
        doFatalCleanup();
    }

    public static void info(String info, Object... args) {
        write("Information", info, args);
    }

    public static void debug(String deb, Object... args) {
        if (Main.DEBUG)
            write("Debugging", deb, args);
    }

    public static void debugTrace(String deb, Object... args) {
        if (!Main.DEBUG) return;
        write("Debug Trace", deb, args);
        try {
            throw new Exception();
        } catch (Exception e) {
            StackTraceElement[] stackTrace = e.getStackTrace();
            for (int i = 4; i < stackTrace.length; i++)
                rawWrite(" - %s.%s:%d\n", stackTrace[i].getClassName(), stackTrace[i].getMethodName(),
                    stackTrace[i].getLineNumber());
        }
    }

    public static void rawWrite(String format, Object... args) {
        String log = String.format(format, args);
        if (logfi != null)
            logfi.println(log);
    }

    private static String getPrevClass() {
        String clas = "";
        try {
            throw new Exception();
        } catch (Exception e) {
            StackTraceElement[] stackTrace = e.getStackTrace();
            clas = stackTrace[3].getClassName() + "." + stackTrace[3].getMethodName();
            if (Main.DEBUG) clas += ":" + stackTrace[3].getLineNumber();
        }
        return clas;
    }

    public static void changeStream(PrintStream a) {
        error = a;
    }

    private static String getTime() {
        String time = "";
        Calendar a = Calendar.getInstance(TimeZone.getDefault());
        time += a.get(Calendar.HOUR_OF_DAY);
        time += ":";
        time += String.format("%02d", a.get(Calendar.MINUTE));
        time += ":";
        time += String.format("%02d", a.get(Calendar.SECOND));
        return time;
    }

    private static void loadlogfile() {
        logLoaded = true;
        File a = new File(GameSettings.configDir + "log.txt");
        try {
            a.createNewFile();
        } catch (IOException ex) {
            Log.warn("Couldn't create the log file! (%s)", ex.getMessage());
        }
        try {
            logfi = new PrintStream(a);
        } catch (FileNotFoundException ex) {
            Log.warn("Couldn't open the log file! (%s)", ex.getMessage());
        }
    }

    private static void doFatalCleanup() {
        GameSettings.deinit();
        Config.crash_deinit();
        System.exit(255);
    }

    public static String getDateTime() {
        return Util.getDateTime();
    }

}
